class AsyncSeriesHook { // 钩子是同步的
  constructor(args) {
    this.tasks = []
  }
  tabAsync(name, task) {
    this.tasks.push(task)
  }

  callAsync(...args) {
    const finalCallback = args.pop()
    let index = 0
    const next = (err, data) => {
      const task = this.tasks[index]
      if (!task || err === 'error') return finalCallback()

      if (index === 0) { // 执行的是第一个
        task(...args, next)
      } else {
        task(data, next)
      }
      index++
    }

    next()
  }
}

const hook = new AsyncSeriesHook(['name'])
hook.tabAsync('react', function (name, cb) {
  setTimeout(() => {
    console.log('react', name)
    cb('error', '结果')
  }, 1000)
})

hook.tabAsync('node', function (data, cb) {
  setTimeout(() => {
    console.log('node', data)
    cb()
  }, 3000);
})

hook.callAsync('jw', function () {
  console.log('end');
})

// AsyncParallelBailHook 带保险异步并发的钩子